[Objective-C] 常量和枚举


#define宏定义
#define是一条预编译指令, 编译器在编译阶段前期会将所有使用到宏的地方简单地进行替换.

在预处理器里进行文本替换,没有类型,不做任何类型检查,编译器可以对相同的字符串进行优化。只保存一份到 .rodata 段。甚至有相同后缀的字符串也可以优化,你可以用GCC 编译测试,”Hello world” 与 “world” 两个字符串,只存储前面一个。取的时候只需要给前面和中间的地址,如果是整形、浮点型会有多份拷贝,但这些数写在指令中。占的只是代码段而已,大量用宏会导致二进制文件变大

#define可以使用类型定义,比如

#define MY_INT_CONSTANT ((int)123)

const
const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝

如果在一个指定单一类里声明常量,在.m 文件顶端用 static const 声明

static NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

如果常量属于一个类,但又要其他类可以访问,在头文件将其声明为 extern ,在.m文件定义

//.h
extern NSString *const MyThingNotificationKey;

//.m
NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

如果它们是全局的常量,在头文件声明,并在相应模块里定义。

只有公有的常量才需要添加命名空间作为前缀。尽管实现文件中私有常量的命名可以遵循另外一种模式,你仍旧可以遵循这个规则。

enum
enum拥有define和const两者的优点,不过enum只能定义整型常量。

如何选择
尽量选择使用const,因为编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率比宏定义要高。

相反,define占据更多的内存空间,因为它只是文字替换,导致存在过多的拷贝。当然这一点是对于一般类型的常量来说的。对于int型常量,引用const的地方拿到的是内存地址,地址数据和int差不多,所以内存上应该不会有太大区别。

另外,const对编译器和调试器来说更加友好。这一点可以作为一个很重要的参考。

记录比较粗略,只是简单整理一下网友讨论,这里用到的具体的语法还是要自己去研究,比如const int 和 int const的区别等。


update at May 20

关于命名规范
常量名(如宏定义、枚举、静态局部变量等)应该以小写字母k开头,使用驼峰格式分隔单词,如:kInvalidHandle,kWritePerm参考

苹果官方文档介绍编码规范提到常量部分:链接

  • 对于一组相关的整型常量,应使用枚举类型
  • 使用const创建浮点型常量。如果这个常量与其他常量没有关联,也可以使用const创建整型常量,否则使用枚举
  • 通常来说,不要使用#define创建常量,使用上两条

update at June 28

这里提到枚举类型,就在这里补充点内容吧。

Apple 文档: Adopting Modern Objective-C

对于 Objective-C 来说,枚举类型建议使用 NS_ENUMNS_OPTIONS 宏。因为它们有更强大的类型检查和代码补全。此外,这个语法提供枚举的方式也兼容旧编译器,当然新编译器可以更好的解析出其隐含的类型信息。

  • 使用 NS_ENUM 宏定义枚举数据,其内容的值都是互斥的:
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
        UITableViewCellStyleDefault,
        UITableViewCellStyleValue1,
        UITableViewCellStyleValue2,
        UITableViewCellStyleSubtitle
};

NS_ENUM 宏不仅定义了枚举的名称(UITableViewCellStyle),还定义了类型(NSInteger),一般来说枚举的类型是 NSInteger

  • NS_OPTIONS 宏定义选项类型,定义一组可以组合的位掩码值:
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
        UIViewAutoresizingNone                 = 0,
        UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
        UIViewAutoresizingFlexibleWidth        = 1 << 1,
        UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
        UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
        UIViewAutoresizingFlexibleHeight       = 1 << 4,
        UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

NS_OPTIONS的定义也包含名称和类型。一般来说选项的类型是 NSUInteger

选项和枚举的差别是枚举只能出现一项,选项可以出现一项或几项,所以选项使用位运算

#define vs const in Objective-C
What is the best way to create constants in Objective-C


文章作者: Wossoneri
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC 4.0 许可协议。转载请注明来源 Wossoneri !
评论
  目录